

class Lock { 
    int readers_;
    int writers_;
    int waiters_;
    Mutex m_;
  public:

    Lock() :
	    readers_( 0 ),
	    writers_( 0 ),
	    waiters_( 0 ) {
    }
    
    void read_lock() {
	Guard g( m_ );

	while ( writers_ || waiters_ ) {
	    conditional.wait( m_ );
	}

	readers_++;
    }
    
    void read_unlock() {
	Guard g( m_ );
	readers_--;
	if ( !readers_ ) {
	    conditional.signal_all( m_ );
	}
    }

    void write_lock() {
	Guard g( m_ );
	while ( writers_ || readers_ ) {
	    waiters_ ++;
	    conditional.wait( m_ );
	    waiters_--;
	}
	writers_ = 1;
    }

    void write_unlock() {
	Guard g( m_ );
	writers_ = 0;
	conditional.signal_all();
    }
};
